package gui.charts;

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

import javax.swing.JFrame;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.util.DefaultShadowGenerator;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.ui.HorizontalAlignment;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.VerticalAlignment;
import org.jfree.util.Rotation;

import data.EffortProvider;
import data.model.ProjectWeek;

public class Chart extends JFrame {

	private static final long serialVersionUID = -668200569707263957L;

	public static Image getPieChart(String chartTitle, EffortProvider provider)
			throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		PieDataset dataset = createPieChartDataset(provider);
		JFreeChart chart = createPieChart(dataset, chartTitle);

		ChartUtilities.writeChartAsPNG(out, chart, 400, 300);

		ImageData imgData = new ImageData(new ByteArrayInputStream(
				out.toByteArray()));

		out.close();
		return new Image(null, imgData);
	}

	public static Image getXYChart(String chartTitle,
			List<ProjectWeek> projectWeeks) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		XYDataset datasetNumbers = createXYChartDatasetNumbers(projectWeeks);
		XYDataset datasetPercentage = createXYChartDatasetPercentages(projectWeeks);
		XYDataset datasetLoC = createXYChartDatasetLoC(projectWeeks);
		JFreeChart chart = createXYChart(datasetNumbers, datasetPercentage,
				datasetLoC, chartTitle);

		ChartUtilities.writeChartAsPNG(out, chart, 400, 300);

		ImageData imgData = new ImageData(new ByteArrayInputStream(
				out.toByteArray()));

		return new Image(null, imgData);
	}

	private static PieDataset createPieChartDataset(EffortProvider provider) {
		DefaultPieDataset dataset = new DefaultPieDataset();
		dataset.setValue(
				Math.round((double) (provider.getEffortProjectManagement())
						/ (double) (provider.getEffort()) * 10000.)
						/ 100. + "% PM", provider.getEffortProjectManagement());
		dataset.setValue(
				Math.round((double) (provider
						.getEffortRequirementsEngineering())
						/ (double) (provider.getEffort()) * 10000.)
						/ 100.
						+ "% RE", provider.getEffortRequirementsEngineering());
		dataset.setValue(
				Math.round((double) (provider.getEffortArchitectureAndDesign())
						/ (double) (provider.getEffort()) * 10000.)
						/ 100. + "% AD",
				provider.getEffortArchitectureAndDesign());
		dataset.setValue(
				Math.round((double) (provider
						.getEffortImplementationAndIntegration())
						/ (double) (provider.getEffort()) * 10000.)
						/ 100.
						+ "% II", provider
						.getEffortImplementationAndIntegration());
		dataset.setValue(
				Math.round((double) (provider.getEffortBuildAndTest())
						/ (double) (provider.getEffort()) * 10000.)
						/ 100. + "% BT", provider.getEffortBuildAndTest());
		return dataset;
	}

	private static XYDataset createXYChartDatasetNumbers(
			List<ProjectWeek> projectWeeks) {
		XYSeries seriesNoT = new XYSeries("NoT");
		XYSeries seriesNoB = new XYSeries("NoB");
		XYSeries seriesNoC = new XYSeries("NoC");
		XYSeries seriesNoTC = new XYSeries("NoTC");

		seriesNoT.add(0, 0);
		seriesNoB.add(0, 0);
		seriesNoC.add(0, 0);
		seriesNoTC.add(0, 0);

		int weekNumber;
		for (ProjectWeek week : projectWeeks) {
			weekNumber = week.getWeekNumber();
			seriesNoT.add(weekNumber, week.getNumberOfTasks());
			seriesNoB.add(weekNumber, week.getNumberOfBugs());
			seriesNoC.add(weekNumber, week.getNumberOfComponents());
			seriesNoTC.add(weekNumber, week.getNumberOfTestCases());
		}
		DefaultXYDataset dataset = new DefaultXYDataset();

		dataset.addSeries("NoT", seriesNoT.toArray());
		dataset.addSeries("NoB", seriesNoB.toArray());
		dataset.addSeries("NoC", seriesNoC.toArray());
		dataset.addSeries("NoTC", seriesNoTC.toArray());

		return dataset;
	}

	private static XYDataset createXYChartDatasetPercentages(
			List<ProjectWeek> projectWeeks) {
		XYSeries seriesPoST = new XYSeries("PoST");
		XYSeries seriesPoCC = new XYSeries("PoCC");

		seriesPoST.add(0, 0);
		seriesPoCC.add(0, 0);

		int weekNumber;
		for (ProjectWeek week : projectWeeks) {
			weekNumber = week.getWeekNumber();
			seriesPoST.add(weekNumber, week.getPercentageOfSuccessfulTests());
			seriesPoCC.add(weekNumber, week.getPercentageOfCodeCoverage());
		}

		DefaultXYDataset dataset = new DefaultXYDataset();

		dataset.addSeries("PoST", seriesPoST.toArray());
		dataset.addSeries("PoCC", seriesPoCC.toArray());

		return dataset;
	}

	private static XYDataset createXYChartDatasetLoC(
			List<ProjectWeek> projectWeeks) {
		XYSeries seriesLoC = new XYSeries("LoC");
		seriesLoC.add(0, 0);

		int weekNumber;
		for (ProjectWeek week : projectWeeks) {
			weekNumber = week.getWeekNumber();
			seriesLoC.add(weekNumber, week.getLinesOfCode());
		}

		DefaultXYDataset dataset = new DefaultXYDataset();
		dataset.addSeries("LoC", seriesLoC.toArray());
		return dataset;
	}

	private static JFreeChart createPieChart(PieDataset dataset, String title) {
		JFreeChart chart = ChartFactory.createPieChart(title, dataset, true,
				false, false);
		chart.setBackgroundPaint(new Color(239, 239, 239));
		chart.getLegend().setBackgroundPaint(Color.LIGHT_GRAY);
		PiePlot plot = (PiePlot) chart.getPlot();
		plot.setStartAngle(290);
		plot.setDirection(Rotation.CLOCKWISE);
		plot.setForegroundAlpha(0.5f);
		return chart;
	}

	private static JFreeChart createXYChart(XYDataset datasetNumbers,
			XYDataset datasetPercentages, XYDataset datasetLoC, String title) {
		XYItemRenderer sRendererLoC = new StandardXYItemRenderer();
		NumberAxis sAxisLoC = new NumberAxis("Lines");
		sAxisLoC.setAutoRangeIncludesZero(true);
		XYPlot sPlotLoC = new XYPlot(datasetLoC, null, sAxisLoC, sRendererLoC);
		sPlotLoC.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
		sPlotLoC.setBackgroundPaint(Color.LIGHT_GRAY);
		sPlotLoC.setOutlinePaint(Color.BLACK);
		sPlotLoC.setOutlineVisible(true);
		sPlotLoC.setDomainGridlinePaint(Color.WHITE);
		sPlotLoC.setDomainCrosshairPaint(Color.WHITE);
		sPlotLoC.setShadowGenerator(new DefaultShadowGenerator());
		sPlotLoC.getRenderer().setSeriesPaint(0, Color.BLACK);

		XYItemRenderer sRendererNumbers = new StandardXYItemRenderer();
		NumberAxis sAxisNumbers = new NumberAxis("Amount");
		sAxisNumbers.setAutoRangeIncludesZero(true);
		XYPlot sPlotNumbers = new XYPlot(datasetNumbers, null, sAxisNumbers,
				sRendererNumbers);
		sPlotNumbers.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
		sPlotNumbers.setBackgroundPaint(Color.LIGHT_GRAY);
		sPlotNumbers.setOutlinePaint(Color.BLACK);
		sPlotNumbers.setOutlineVisible(true);
		sPlotNumbers.setDomainGridlinePaint(Color.WHITE);
		sPlotNumbers.setDomainCrosshairPaint(Color.WHITE);
		sPlotNumbers.setShadowGenerator(new DefaultShadowGenerator());
		sPlotNumbers.getRenderer().setSeriesPaint(0, Color.GRAY);
		sPlotNumbers.getRenderer().setSeriesPaint(1, Color.BLUE);
		sPlotNumbers.getRenderer().setSeriesPaint(2, Color.RED);
		sPlotNumbers.getRenderer().setSeriesPaint(3, Color.MAGENTA);

		XYItemRenderer sRendererPercentages = new StandardXYItemRenderer();
		NumberAxis sAxisPercentages = new NumberAxis("Percent");
		sAxisPercentages.setAutoRangeIncludesZero(true);
		XYPlot sPlotPercentages = new XYPlot(datasetPercentages, null,
				sAxisPercentages, sRendererPercentages);
		sPlotPercentages.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
		sPlotPercentages.setBackgroundPaint(Color.LIGHT_GRAY);
		sPlotPercentages.setOutlinePaint(Color.BLACK);
		sPlotPercentages.setOutlineVisible(true);
		sPlotPercentages.setDomainGridlinePaint(Color.WHITE);
		sPlotPercentages.setDomainCrosshairPaint(Color.WHITE);
		sPlotPercentages.setShadowGenerator(new DefaultShadowGenerator());
		sPlotPercentages.getRenderer().setSeriesPaint(0, Color.ORANGE);
		sPlotPercentages.getRenderer().setSeriesPaint(1, Color.WHITE);

		CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis(
				"Week"));
		plot.getDomainAxis().setNegativeArrowVisible(false);
		plot.getDomainAxis().setStandardTickUnits(
				NumberAxis.createIntegerTickUnits());
		plot.add(sPlotLoC, 1);
		plot.add(sPlotNumbers, 1);
		plot.add(sPlotPercentages, 1);
		plot.setOrientation(PlotOrientation.VERTICAL);
		plot.setGap(10d);

		JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
				plot, true);
		chart.setAntiAlias(true);
		chart.setBackgroundPaint(new Color(239, 239, 239));

		LegendTitle legend = chart.getLegend();
		legend.setPosition(RectangleEdge.BOTTOM);
		legend.setHorizontalAlignment(HorizontalAlignment.CENTER);
		legend.setBackgroundPaint(Color.LIGHT_GRAY);
		legend.setItemPaint(Color.BLACK);
		legend.setHorizontalAlignment(HorizontalAlignment.RIGHT);
		legend.setVerticalAlignment(VerticalAlignment.CENTER);

		return chart;
	}
}
